package cn.tedu.mall.seckill.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.JsonPage;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuDetailSimpleVO;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuVO;
import cn.tedu.mall.seckill.service.ISeckillSpuService;
import cn.tedu.mall.seckill.utils.RedisBloomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;

@Service
public class SeckillSpuServiceImpl implements ISeckillSpuService {
    @Autowired
    private RedisTemplate redisTemplate;

    public static final String SECKILL_SPUS_KEY = "sekill:spus";

    @Override
    public JsonPage<SeckillSpuVO> listSeckillSpus(Integer page, Integer pageSize) {
        //所有数据查询 在秒杀都走缓存
        List<SeckillSpuVO> spus =
                (List<SeckillSpuVO>) redisTemplate.opsForValue().get(SECKILL_SPUS_KEY);
        //简单判断一下
        if (spus == null || spus.size() == 0) {
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND, "当前缓存没有数据,请检查预热逻辑");
        }
        return JsonPage.defaultPage(spus);
    }

    //添加布隆过滤器 判断spuId是否存在,存在,才继续,不存在直接抛异常
    @Autowired
    private RedisBloomUtils redisBloomUtils;

    //定义布隆过滤器,存储所有spuId的key值
    public static final String SECKILL_BLOOM_SPUS_KEY = "seckill:bloom:spus";

    public static final String SECKILL_SPU_PREFIX = "sekill:spu:";

    @Override
    public SeckillSpuVO getSeckillSpu(Long spuId) {
        Boolean exists = redisBloomUtils.bfexists(SECKILL_BLOOM_SPUS_KEY, spuId + "");
        if (!exists) {
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND, "当前数据中没有spuId:" + spuId);
        }
        SeckillSpuVO seckillSpuVO =
                (SeckillSpuVO) redisTemplate.opsForValue().get(SECKILL_SPU_PREFIX + spuId);
        if (seckillSpuVO == null) {
            throw new CoolSharkServiceException(
                    ResponseCode.NOT_FOUND, "当前缓存没有数据,请检查预热逻辑");
        }
        //判断当前系统时间,是否在秒杀时间段内,如果不在时间段,url不带回去
        LocalDateTime now = LocalDateTime.now();
        Duration afterStart = Duration.between(now, seckillSpuVO.getStartTime());//>0则表示秒杀还没开始
        Duration beforeEnd = Duration.between(seckillSpuVO.getEndTime(), now);//>0则表示秒杀已经结束
        //根据between方法解释,定义获取时间对比值afterStart now>start
        //beforeEnd end>now 两个条件有一个不满足,说明秒杀时间和当前系统时间不匹配
        //判断是否为负数，负数则时间合法，取反则为不合法
        if (!(afterStart.isNegative() && beforeEnd.isNegative())) {
            //时间不合法,url不要带
            seckillSpuVO.setUrl(null);
        }
        return seckillSpuVO;
    }

    public static final String SECKILL_SPUDETAIL_PREFIX = "sekill:spuDetail:";

    @Override
    public SeckillSpuDetailSimpleVO getSeckillSpuDetail(Long spuId) {
        //UNDO 自行实现
        SeckillSpuDetailSimpleVO seckillSpuDetailSimpleVO =
                (SeckillSpuDetailSimpleVO) redisTemplate.opsForValue().get(SECKILL_SPUDETAIL_PREFIX + spuId);
        if (seckillSpuDetailSimpleVO == null) {
            throw new CoolSharkServiceException
                    (ResponseCode.NOT_FOUND, "当前缓存没有数据,请检查预热逻辑");
        }
        return seckillSpuDetailSimpleVO;
    }
}
